﻿//*********************************************************************
//
//  文件名：OAuth2OAuthAuthorizationServerProvider
//
//  作者： LW
//
//  作用：
//
//  日期：2015/9/8 16:14:09
//
//*********************************************************************
using System;
using Microsoft.Owin.Security.OAuth;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.Owin.Security;
using System.Collections.Generic;

using YouTravel.DomainService;
using YouTravel.DomainModels;
using Framework.Common;
using Framework.IOC;
using YouTravel.Framework.Enums;
using YouTravel.ViewModels;
using Framework.Common.Exceptions;

namespace Application.WebAPI.Provider
{
    /// <summary>
    /// OAuth2OAuthAuthorizationServerProvider
    /// 应用程序提供和 OAuth 认证中间件交互的 IOAuthAuthorizationServerProvider 实例
    /// </summary>
    public class OAuth2OAuthAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        private readonly IUserService userService = ServiceLocator.Instance.GetService<IUserService>();

        //private readonly IUserService userService = new UserService();
        protected CommonMD5 commonMD5 = CommonMD5.getInstance();

        /// <summary>
        /// 第一步：客户端认证
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string grant_type = context.Parameters[Paths.GrantType];

            if (grant_type == Paths.GrantTypes.Password)
            {
                string username = context.Parameters[Paths.UserName];
                string password = context.Parameters[Paths.Password];

                //调用登录逻辑
                UserViewModel user = this.Login(username, password);
                if (user != null)
                {
                    //把当前用户存入上下文
                    context.OwinContext.Set<UserViewModel>("loginuser", user);
                    bool flag = context.Validated();
                }
                else
                {
                    //context.Rejected();
                    //context.Rejected();
                    //return;
                    throw new BusinessException("请确认用户名和密码输入正确");
                }
            }
            else if (grant_type == Paths.GrantTypes.RefreshToken)
            {
                bool flag = context.Validated();
            }
            else
            {
                throw new BusinessException("refresh token error");
                //context.Rejected();
                //return;
            }
            #region 其他两种认证方式 暂时不做
            //else if (grant_type == Paths.GrantTypes.ClientCredentials || grant_type == Paths.GrantTypes.AuthorizationCode)
            //{
            //    string clientId;
            //    string clientSecret;
            //    //TryGetBasicCredentials 指Client可以按照Basic身份验证的规则提交ClientId和ClientSecret
            //    //TryGetFormCredentials  指Client可以把ClientId和ClientSecret放在Post请求的form表单中提交
            //    if (context.TryGetBasicCredentials(out clientId, out clientSecret) || context.TryGetFormCredentials(out clientId, out clientSecret))
            //    {
            //        //grant_type:client_credentials
            //        //暂时不支持
            //        context.Rejected();
            //        return;
            //    }
            //}
            #endregion
        }

        /// <summary>
        /// 第二步：授予资源所有者凭据
        /// grant_type:password
        /// 如：grant_type=password&username=admin&password=123456
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            //获取用户信息、验证用户身份合法性
            UserViewModel loginuser = context.OwinContext.Get<UserViewModel>("loginuser");

            string clientId = context.UserName;
            string clientSecret = context.Password;


            var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
            oAuthIdentity.AddClaim(new Claim("sub", loginuser.ID.ToString()));
            oAuthIdentity.AddClaim(new Claim("role", "user"));

            // 创建元数据传递到刷新令牌提供程序
            var props = new AuthenticationProperties(new Dictionary<string, string>
                    {
                        { "as:client_id", loginuser.ID.ToString() }
                    });

            var ticket = new AuthenticationTicket(oAuthIdentity, props);
            bool flag = context.Validated(ticket);
        }

        /// <summary>
        /// 授予刷新令牌
        /// 验证持有 refresh token 的客户端
        /// grant_type:refresh_token
        /// 如：grant_type=refresh_token&refresh_token=fd08939b38e94f0ba154b8c51f57d256fb919fc818f4437ea24fd30fbc7c1936
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
        {
            //获取'第二步'创建的元数据
            var originalClient = context.Ticket.Properties.Dictionary["as:client_id"];

            //获取用户信息、验证用户身份合法性

            // 刷新令牌请求更改身份验证的机会
            var newId = new ClaimsIdentity(context.Ticket.Identity);
            newId.AddClaim(new Claim("newClaim", "refreshToken"));

            var newTicket = new AuthenticationTicket(newId, context.Ticket.Properties);
            bool flag = context.Validated(newTicket);
        }

        private UserViewModel Login(string account, string pwd)
        {
            pwd = commonMD5.MD5(pwd);

            UserViewModel user = userService.Login(account, pwd);
            //user.Token = "";

            //缓存
            bool flag = RedisHelp.CacheLoginUser(user);
            var tmp = RedisHelp.GetLoginUserCache(user.ID);
            return user;
        }
    }
}